package hn.sigit.logic.workflow.transaction.impl;

import hn.sigit.dao.hnd.administrative.HND_TransactionMetaDataDAO;
import hn.sigit.dao.hnd.ladmshadow.ParcelDAO;
import hn.sigit.dao.hnd.ladmshadow.PropertyDAO;
import hn.sigit.logic.general.GeneralHelper;
import hn.sigit.logic.general.ResourceBundleHelper;
import hn.sigit.logic.ladm.PropertyUtil;
import hn.sigit.logic.viewer.InteractiveViewerHelper;
import hn.sigit.logic.viewer.MapHelper;
import hn.sigit.logic.viewer.toolbox.ViewerCallable;
import hn.sigit.logic.workflow.transaction.DataEntryHelper;
import hn.sigit.logic.workflow.transaction.TransactionHelper;
import hn.sigit.model.commons.IParcel;
import hn.sigit.model.commons.IProperty;
import hn.sigit.model.commons.ISpatialZone;
import hn.sigit.model.hnd.administrative.HND_TransactionMetaData;
import hn.sigit.model.hnd.ladmshadow.Parcel;
import hn.sigit.model.hnd.ladmshadow.Property;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.ejb.Remove;
import javax.faces.model.SelectItem;

import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;

import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.io.WKTWriter;

@Name(DataEntryHelper.NAME)
@Scope(value=ScopeType.CONVERSATION)
@AutoCreate
public class DataEntryHelperImpl implements DataEntryHelper, ViewerCallable, Serializable {
	private static final long serialVersionUID = 1L;

	private TransactionHelper transactionHelper;
	
	private List<SelectItem> siRequestedParcels;

	private long presentationId;
	
	private List<Property> requestedProperties;
	private List<Property> neighborProperties;
	private List<Parcel> requestedParcels;
	private List<Parcel> neighborParcels;
	
	private List<String> presentationWkts = new ArrayList<String>();
	private ResourceBundleHelper resBundle;
	
	private GeneralHelper generalHelper = (GeneralHelper) Component.getInstance(GeneralHelper.NAME, true);
	private MapHelper mapHelper = (MapHelper) Component.getInstance(MapHelper.NAME, true);
	private InteractiveViewerHelper interactiveViewerHelper = (InteractiveViewerHelper) Component.getInstance(InteractiveViewerHelper.NAME, true);
	
	private boolean canMutateRRR = true;
	private boolean canSplit = true;
	private boolean canMerge = true;
	private boolean canEditData = true;
	
	
	public DataEntryHelperImpl() {
		transactionHelper = (TransactionHelper) Component.getInstance(TransactionHelper.NAME);
		presentationId = transactionHelper.getTransactionId();
		
		interactiveViewerHelper.setPresentationId(presentationId);
		interactiveViewerHelper.getMergeHelper().setViewerCallable(this);
		interactiveViewerHelper.setSelectedZone( getRequestedParcels().get(0) );
		interactiveViewerHelper.addAditionalReRenderId("drawParcelFunctions");
		interactiveViewerHelper.addAditionalReRenderId("requestedParcelList");
		interactiveViewerHelper.setSplitCallable(new DataEntrySplitViewerCallable(this));
		interactiveViewerHelper.setAllowEditing(true);

		mapHelper.setHighlightParcelList(false);
		mapHelper.setShowEditControls(true);
		
		HND_TransactionMetaData tmd = HND_TransactionMetaDataDAO.loadRequestMetaDataByRequestType(
				transactionHelper.getTransaction().getRequestType());
		if (tmd != null) {
			canMutateRRR = tmd.isCanMutateRRR();
			canSplit = tmd.isCanSplit();
			canMerge = tmd.isCanMerge();
			canEditData = tmd.isCanEditData();
		}
		
		updatePresentationWkts();
	}
	
	@Override
	public long getPresentationId() {
		return presentationId;
	}
	
	@Override
	public ISpatialZone getSelectedZone() {
		return interactiveViewerHelper.getSelectedZone();
	}
	
	@Override
	public Double getEnvelopeLeft() {
		return interactiveViewerHelper.getEnvelopeLeft();
	}
	@Override
	public Double getEnvelopeBottom() {
		return interactiveViewerHelper.getEnvelopeBottom();
	}
	@Override
	public Double getEnvelopeRight() {
		return interactiveViewerHelper.getEnvelopeRight();
	}
	@Override
	public Double getEnvelopeTop() {
		return interactiveViewerHelper.getEnvelopeTop();
	}

	@Override
	public List<Property> getRequestedProperties() {
		if (requestedProperties == null) {
			if (this.presentationId != 0)
				requestedProperties = PropertyDAO.loadRequestedPropertiesByPresentationId(this.presentationId);
			else
				requestedProperties = new ArrayList<Property>();
		}
		
		return requestedProperties;
	}
	@Override
	public void setRequestedProperties(List<Property> requestedProperties) {
		this.requestedProperties = requestedProperties;
	}
	
	@Override
	public List<Property> getNeighborProperties() {
		if (neighborProperties == null) {
			neighborProperties = PropertyDAO.loadNeighborPropertiesByPresentationId(this.presentationId);
		}
		
		return neighborProperties;
	}
	@Override
	public void setNeighborProperties(List<Property> neighborProperties) {
		this.neighborProperties = neighborProperties;
	}
	
	@Override
	public List<Parcel> getRequestedParcels() {
		if (requestedParcels == null) {
			requestedParcels = ParcelDAO.loadRequestedParcelsByPresentationId(this.presentationId);
		}
		
		return requestedParcels;
	}
	@Override
	public void setRequestedParcels(List<Parcel> requestedParcels) {
		this.requestedParcels = requestedParcels;
	}
	
	@Override
	public List<Parcel> getNeighborParcels() {
		if (neighborParcels == null) {
			neighborParcels = ParcelDAO.loadNeighborParcelsByPresentationId(this.presentationId);
		}
		
		return neighborParcels;
	}
	@Override
	public void setNeighborParcels(List<Parcel> neighborParcels) {
		this.neighborParcels = neighborParcels;
	}
	
	@Override
	public String getRequestedParcelsGML() {
		return generalHelper.getSpatialZonesGML(this.getRequestedParcels(), 0);
	}
	@Override
	public String getNeighborParcelsGML() {
		return generalHelper.getSpatialZonesGML(this.getNeighborParcels(), 1);
	}
	
	@Override
	public TransactionHelper getTransactionHelper() {
		return transactionHelper;
	}
	
	@Override
	public ResourceBundleHelper getResBundle() {
		if (resBundle == null) {
			resBundle = generalHelper.getResBundle();
		}
		return resBundle;
	}

	private void updatePresentationWkts() {
		presentationWkts.clear();

		List<Property> propertyList = PropertyDAO.loadPropertiesByPresentationId(presentationId);
		WKTWriter wktWriter = new WKTWriter();
		for (Property prop : propertyList) {
			for (Polygon p : PropertyUtil.polygonsFromProperty(prop))
				presentationWkts.add(wktWriter.write(p));
		}
	}

	
	@Override
	public List<SelectItem> getSiRequestedParcels() {
		if (siRequestedParcels == null) {
			siRequestedParcels = new ArrayList<SelectItem>();
			/*
			for (Parcel p : getRequestedParcels())
				siRequestedParcels.add(new SelectItem(p, parcelText(p)));
				*/
		}
		return siRequestedParcels;
	}
	
	public boolean isEditing() {
		return interactiveViewerHelper.isEditing();
	}

	@Override
	public void afterMerge(IParcel parcel1, IProperty property1,
			IParcel parcel2, IProperty property2, Polygon newShape,
			Date timeStamp) {
		setRequestedParcels(null);
		setNeighborParcels(null);
	}

	@Override
	public void doBorderOperation(
			InteractiveViewerHelper interactiveViewerHelper) {
	}

	@Override
	public boolean isCanMutateRRR() {
		return canMutateRRR;
	}

	@Override
	public boolean isCanSplit() {
		return canSplit;
	}

	@Override
	public boolean isCanMerge() {
		return canMerge;
	}

	@Override
	public boolean isCanEditData() {
		return canEditData;
	}

	@Override
	@Destroy @Remove
	public void destroy() {}

}
